package rad.framework.seam;

import java.io.InputStream;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import rad.framework.lang.ExceptionUtil;
import rad.framework.lang.IOUtil;
import rad.framework.validator.ValidationUtil;
import rad.framework.xml.BetwixtUtil;

import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
import org.hibernate.validator.InvalidValue;
import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.Logger;
import org.jboss.seam.annotations.Observer;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.annotations.Transactional;
import org.jboss.seam.core.ResourceLoader;
import org.jboss.seam.log.Log;
import org.jboss.seam.transaction.Transaction;

/**
 * Extend this class per application to initialize data.
 * 
 * @author boudyacho
 * 
 */
@Scope(ScopeType.APPLICATION)
public class ImportInit {

	@Logger
	private Log log;

	private Set<String> fileNames;

	public void setFileNames(Set<String> fileNames) {
		this.fileNames = fileNames;
	}

	@Observer("org.jboss.seam.postInitialization")
	@Transactional
	public void init() throws Exception {
//		ConvertUtils.register(new DateConverter(), Date.class);
		log.debug("Importing: {0}", this);
		Map<String, Object> hits = new HashMap<String, Object>();
		for (String fileName : fileNames) {
			String xml = getXml(fileName);
			if (xml != null) {
				importXml(fileName, xml, hits);
			}
		}
	}

	protected String getXml(String fileName) {
		InputStream is = ResourceLoader.instance()
				.getResourceAsStream(fileName);
		if (is == null) {
			log.error("#0:  Not found.", fileName);
			return null;
		} else {
			return IOUtil.convertStreamToString(is);
		}
	}

	protected void importXml(String fileName, String xml, Map<String, Object> hits) throws Exception {
		try {
			List<Object> list = (List<Object>) BetwixtUtil.importXml(xml, null);
			ImportUtil.doImport(list, hits);
			log.info("Loaded: #0", fileName);
		} catch (Throwable e) {
			Transaction.instance().setRollbackOnly();

			Throwable cause = ExceptionUtil.getRootCause(e);
			log.error(cause.getMessage());

			InvalidValue[] errors = ValidationUtil.getInvalidValues(cause);
			if (errors.length > 0) {
				log.error("Validation Errors: " + Arrays.toString(errors));
			}
		}
	}

	public String toString() {
		return ToStringBuilder.reflectionToString(this,
				ToStringStyle.MULTI_LINE_STYLE);
	}
}
